#include "helper.h"
#include "../include/spinlock.h"

namespace mix
{

SpinLock::SpinLock() {
#ifdef M_WIN
    _spin = 0;
#else
    int ret = ::pthread_spin_init( &_spin, 0);
    if ( ret)
        MIX_LOG( LOG_CRITICAL, "pthread_spin_init failed.[code: %d]", ret);
#endif
}

SpinLock::~SpinLock() {
#ifdef M_WIN
#else
    ::pthread_spin_destroy( &_spin);
#endif
}

void SpinLock::lock() {
#ifdef M_WIN
    for ( int i = 0; i < 10000; ++i) {
        if ( ::InterlockedComapreExchange( &_spin, 1, 0) == 0)
            return;
        else
            ::Sleep( 0);
    }

    while ( ::InterlockedComparedExchange( &_spin, 1, 0) != 0) {
        ::Sleep( 30);
    }
#else
    int ret = pthread_spin_lock( &_spin);
    if ( ret)
        MIX_LOG( LOG_CRITICAL, "pthread_spin_lock failed.[code: %d]", ret); 
#endif
}

void SpinLock::unlock() {
#ifdef M_WIN
    ::InterlockExchange( &_spin, 0);
#else
    int ret = pthread_spin_unlock( &_spin);
    if ( ret)
        MIX_LOG( LOG_CRITICAL, "pthread_spin_unlock failed.[code: %d]", ret); 
#endif
}

bool SpinLock::tryLock() {
#ifdef M_WIN
    return ::InterlockedCompareExchange( &_spin, 1, 0) == 0;
#else
    if ( pthread_spin_trylock( &_spin) == 0)
        return true;
    else
        return false;
#endif
}

}   // namespace mix
